// 文件名：span_simd_kernel.cpp
// 目的：用 std::span 传递可变视图，对浮点块进行按因子缩放；在可用 AVX2 时走 SIMD 路径，否则退化为标量实现。
// 设计：
//   - 对齐检查：通过 std::as_bytes(data).data() 获取底层字节地址，简单判断 32 字节对齐性（仅提示）；
//   - AVX2：宽度 8 的向量批处理，loadu/storeu 处理任意对齐；尾部不足用标量补齐；
//   - 非 AVX2：纯标量循环；
//   - 使用 std::span<float> 传递可变视图，可对子数组/切片直接操作（零拷贝）。
// 注意：
//   - loadu/storeu 不要求对齐，但对齐可提升性能；
//   - 编译需开启 AVX2（如 -mavx2）；否则走 #else 分支；
//   - 实际工程中应考虑 FMA、对齐加载、预取与更复杂的边界处理。

#include <cstddef>
#include <immintrin.h>
#include <iostream>
#include <span>
#include <vector>

// 简化示例：如果可用 AVX2，则使用；否则用标量实现
void scaleKernel(std::span<float> data, float factor) {
    const std::byte* ptr = std::as_bytes(data).data();
    if (reinterpret_cast<std::uintptr_t>(ptr) % alignof(__m256) != 0) {
        std::cerr << "Warning: data not aligned to 32 bytes, fallback to scalar\n";
    }

#if defined(__AVX2__)
    std::size_t i = 0;
    __m256 vecFactor = _mm256_set1_ps(factor);
    const std::size_t width = 8;

    for (; i + width <= data.size(); i += width) {
        __m256 value = _mm256_loadu_ps(&data[i]);
        value = _mm256_mul_ps(value, vecFactor);
        _mm256_storeu_ps(&data[i], value);
    }
    for (; i < data.size(); ++i) {
        data[i] *= factor;
    }
#else
    for (float& v : data) {
        v *= factor;
    }
#endif
}

int main() {
    std::vector<float> samples(32);
    for (std::size_t i = 0; i < samples.size(); ++i) {
        samples[i] = static_cast<float>(i);
    }

    std::span<float> chunk = std::span(samples).subspan(4, 16);
    scaleKernel(chunk, 1.5f);

    for (float v : chunk) {
        std::cout << v << ' ';
    }
    std::cout << '\n';

    return 0;
}